package com.lingjtx.common.core.util;

import com.lingjtx.common.core.RedisOptions;
import com.lingjtx.common.core.algorithm.RSAUtil;
import com.lingjtx.common.core.constant.Const;
import com.lingjtx.common.core.constant.RedisConfig;
import com.lingjtx.common.core.constant.SignatureType;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class SignatureHelper {

    // 1-校验成功；2-时间戳不在有效窗口内；3-随机数已存在；4-验签错误
    public static SignatureType verify(String headerSignature, String body, RedisOptions redis) {
        if (StringUtil.isNotEmpty(headerSignature)) {
            // timestamp=xxx,nonce=xxx,sign=xxx
            Map<String, String> map = parseStringToMap(headerSignature);
            if (!map.isEmpty()) {
                String timestamp = map.get("timestamp");
                String nonce = map.get("nonce");
                String sign = map.get("sign");
                if (StringUtil.isNotEmpty(timestamp)) {
                    long time = Long.parseLong(timestamp);
                    if (isExpire(time)) {
                        return SignatureType.TIMESTAMP;
                    }
                }
                if (hasNonce(nonce, redis)) {
                    return SignatureType.NONCE;
                }
                String content = timestamp + "\n"
                        + nonce + "\n"
                        + body + "\n";
                if (RSAUtil.verify(content, sign, Const.API_RSA_PUB_KEY)) {
                    return SignatureType.SUCCESS;
                }
            }
        }
        return SignatureType.FAIL;
    }

    private static boolean hasNonce(String nonce, RedisOptions redis) {
        if (!redis.exists(RedisConfig.KEY_API_SIGNATURE + nonce)) {
            redis.set(RedisConfig.KEY_API_SIGNATURE + nonce, "SignatureHelper nonce check", RedisConfig.TIMEOUT_10_MIN);
            return false;
        }
        return true;
    }

    private static boolean isExpire(long timestamp) {
        Date expTime = new Date(timestamp + RedisConfig.TIMEOUT_5_MIN * 1000);
        return expTime.before(new Date()); // 过期
    }

    private static Map<String, String> parseStringToMap(String headerSignature) {
        Map<String, String> resultMap = new HashMap<>();

        // 1. 按逗号分割每个键值对
        String[] pairs = headerSignature.split(",");

        for (String pair : pairs) {
            // 2. 按等号分割键和值
            String[] keyValue = pair.split(":");

            // 3. 检查是否为有效的键值对
            if (keyValue.length == 2) {
                String key = keyValue[0].trim();
                String value = keyValue[1].trim();
                resultMap.put(key, value);
            }
        }
        return resultMap;
    }
}
